#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/slab.h>

static struct task_struct * slam_unbind_thread = NULL;

static int slam_bind_func(void *data)
{
	unsigned int cur_cpu = *((unsigned int *)data);

	printk("[slam_bind_thread/%d] start!\n", cur_cpu);
	while(!kthread_should_stop())
	{
		printk("I'm in [slam_bind_thread/%d]!\n", cur_cpu);
		schedule_timeout(msecs_to_jiffies(5000));
	}
	printk("[slam_bind_thread/%d] end!\n", cur_cpu);

	return 0;
}

static int slam_unbind_func(void *data)
{
	char *slam_data = kzalloc(strlen(data)+1, GFP_KERNEL);
	strncpy(slam_data, data, strlen(data));
	while(!kthread_should_stop())
	{
		printk("Unbind Thread:%s(%ld)\n", slam_data, jiffies);
		schedule_timeout(msecs_to_jiffies(5000));
	}
	kfree(slam_data);
	return 0;
}

static __init int kthread_example_init(void)
{
	int cur_cpu;
	unsigned int cpus = num_online_cpus();
	unsigned int bind_thread_params[cpus];
	struct task_struct *slam_bind_threads[cpus];

	slam_unbind_thread = kthread_run(slam_unbind_func, "slam-xinu", "slam_unbind");

	for_each_present_cpu(cur_cpu)
	{
		bind_thread_params[cur_cpu] = cur_cpu;
		slam_bind_threads[cur_cpu] = kthread_create(slam_bind_func, (void *)(bind_thread_params+cur_cpu), "BindThread/%d", cur_cpu);
		kthread_bind(slam_bind_threads[cur_cpu], cur_cpu);
		wake_up_process(slam_bind_threads[cur_cpu]);
	}

	schedule_timeout_interruptible(msecs_to_jiffies(30*1000));

	for(cur_cpu=0;cur_cpu<cpus;cur_cpu++)
	{
		kthread_stop(slam_bind_threads[cur_cpu]);
	}

	return 0;
}

static __exit void kthread_example_exit(void)
{
	if(slam_unbind_thread)
	{
		kthread_stop(slam_unbind_thread);
	}
}

module_init(kthread_example_init);
module_exit(kthread_example_exit);
